home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / ROM_Kernel_Manuals / Lib_examples / menulayout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-20  |  19.8 KB  |  552 lines

  1. ;/* menulayout.c - Execute me to compile me with SAS C 5.10
  2. LC -b1 -cfistq -v -y -j73 menulayout.c
  3. Blink FROM LIB:c.o,menulayout.o TO menulayout LIBRARY LIB:LC.lib,LIB:Amiga.lib
  4. quit
  5. ** menulayout.c - Example showing how to do menu layout in general.  This example
  6. ** also illustrates handling menu events, including IDCMP_MENUHELP events.
  7. **
  8. ** Note that handling arbitrary fonts is fairly complex.  Applications that require V37
  9. ** should use the simpler menu layout routines found in the GadTools library.
  10. */
  11. #define INTUI_V36_NAMES_ONLY
  12.  
  13. #include <exec/types.h>
  14. #include <intuition/intuition.h>
  15. #include <intuition/intuitionbase.h>
  16. #include <graphics/gfxbase.h>
  17. #include <dos/dos.h>
  18. #include <clib/exec_protos.h>
  19. #include <clib/graphics_protos.h>
  20. #include <clib/intuition_protos.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24.  
  25. #ifdef LATTICE
  26. int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
  27. int chkabort(void) { return(0); }  /* really */
  28. #endif
  29. /* Our function prototypes */
  30. BOOL processMenus(USHORT selection, BOOL done);
  31. BOOL handleIDCMP(struct Window *win);
  32. USHORT MaxLength(struct RastPort *textRPort, struct MenuItem *first_item, USHORT char_size);
  33. VOID setITextAttr(struct IntuiText *first_IText, struct TextAttr *textAttr);
  34. VOID adjustItems(struct RastPort *textRPort, struct MenuItem *first_item, struct TextAttr *textAttr,
  35.                  USHORT char_size, USHORT height, USHORT level, USHORT left_edge);
  36. BOOL adjustMenus(struct Menu *first_menu, struct TextAttr *textAttr);
  37. LONG doWindow(void);
  38.  
  39. /* Settings Item IntuiText */
  40. struct IntuiText SettText[] = {
  41.         {0,1,JAM2,2,         1, NULL, "Sound...",        NULL },
  42.         {0,1,JAM2,CHECKWIDTH,1, NULL, " Auto Save",      NULL },
  43.         {0,1,JAM2,CHECKWIDTH,1, NULL, " Have Your Cake", NULL },
  44.         {0,1,JAM2,CHECKWIDTH,1, NULL, " Eat It Too",     NULL }
  45.     };
  46.  
  47. struct MenuItem SettItem[] = {
  48.     { /* "Sound..." */
  49.         &SettItem[1], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  50.         (APTR)&SettText[0], NULL, NULL, NULL, MENUNULL },
  51.         { /* "Auto Save" (toggle-select, initially selected) */
  52.         &SettItem[2], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT|MENUTOGGLE|CHECKED, 0,
  53.         (APTR)&SettText[1], NULL, NULL, NULL, MENUNULL },
  54.     { /* "Have Your Cake" (initially selected, excludes "Eat It Too") */
  55.         &SettItem[3], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT|CHECKED, 8,
  56.         (APTR)&SettText[2], NULL, NULL, NULL, MENUNULL },
  57.         { /* "Eat It Too" (excludes "Have Your Cake") */
  58.         NULL, 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT, 4,
  59.         (APTR)&SettText[3], NULL, NULL, NULL, MENUNULL }
  60.     };
  61.  
  62. /* Edit Menu Item IntuiText */
  63. struct IntuiText EditText[] = {
  64.         {0,1,JAM2,2,1, NULL, "Cut",       NULL },
  65.         {0,1,JAM2,2,1, NULL, "Copy",      NULL },
  66.         {0,1,JAM2,2,1, NULL, "Paste",     NULL },
  67.         {0,1,JAM2,2,1, NULL, "Erase",     NULL },
  68.         {0,1,JAM2,2,1, NULL, "Undo",      NULL }
  69.     };
  70.  
  71. /* Edit Menu Items */
  72. struct MenuItem EditItem[] = {
  73.         { /* "Cut" (key-equivalent: 'X') */
  74.         &EditItem[1], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  75.         (APTR)&EditText[0], NULL, 'X', NULL, MENUNULL },
  76.         { /* "Copy" (key-equivalent: 'C') */
  77.         &EditItem[2], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  78.         (APTR)&EditText[1], NULL, 'C', NULL, MENUNULL },
  79.         { /* "Paste" (key-equivalent: 'V') */
  80.         &EditItem[3], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  81.         (APTR)&EditText[2], NULL, 'V', NULL, MENUNULL },
  82.         { /* "Erase" (disabled) */
  83.         &EditItem[4], 0, 0, 0, 0, ITEMTEXT|HIGHCOMP, 0,
  84.         (APTR)&EditText[3], NULL, NULL, NULL, MENUNULL },
  85.         { /* "Undo" MenuItem (key-equivalent: 'Z') */
  86.         NULL, 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  87.         (APTR)&EditText[4], NULL, 'Z', NULL, MENUNULL }
  88.     };
  89.  
  90. /* IntuiText for the Print Sub-Items */
  91. struct IntuiText PrtText[] = {
  92.         {0,1, JAM2,2,1, NULL, "NLQ",   NULL },
  93.         {0,1, JAM2,2,1, NULL, "Draft", NULL }
  94.     };
  95.  
  96. /* Print Sub-Items */
  97. struct MenuItem PrtItem[] = {
  98.         { /* "NLQ" */
  99.         &PrtItem[1], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  100.         (APTR)&PrtText[0], NULL, NULL, NULL, MENUNULL },
  101.         { /* "Draft" */
  102.         NULL, 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  103.         (APTR)&PrtText[1], NULL, NULL, NULL, MENUNULL }
  104.     };
  105. /* Uses the >> character to indicate a sub-menu item.
  106. ** This is \273 Octal, 0xBB Hex or Alt-0 from the Keyboard.
  107. **
  108. ** NOTE that standard menus place this character at the right margin of the menu box.
  109. ** This may be done by using a second IntuiText structure for the single character,
  110. ** linking this IntuiText to the first one, and positioning the IntuiText so that the
  111. ** character appears at the right margin.  GadTools library will provide the correct behavior.
  112. */
  113.  
  114. /* Project Menu Item IntuiText */
  115. struct IntuiText ProjText[] = {
  116.         {0,1, JAM2,2,1, NULL, "New",         NULL },
  117.         {0,1, JAM2,2,1, NULL, "Open...",     NULL },
  118.         {0,1, JAM2,2,1, NULL, "Save",        NULL },
  119.         {0,1, JAM2,2,1, NULL, "Save As...",  NULL },
  120.         {0,1, JAM2,2,1, NULL, "Print     \273", NULL },
  121.         {0,1, JAM2,2,1, NULL, "About...",    NULL },
  122.         {0,1, JAM2,2,1, NULL, "Quit",        NULL }
  123.     };
  124.  
  125.  
  126. /* Project Menu Items */
  127. struct MenuItem ProjItem[] = {
  128.         { /* "New" (key-equivalent: 'N' */
  129.         &ProjItem[1],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  130.         (APTR)&ProjText[0], NULL, 'N', NULL, MENUNULL },
  131.         { /* "Open..." (key-equivalent: 'O') */
  132.         &ProjItem[2],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  133.         (APTR)&ProjText[1], NULL, 'O', NULL, MENUNULL },
  134.         { /* "Save" (key-equivalent: 'S') */
  135.         &ProjItem[3],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  136.         (APTR)&ProjText[2], NULL, 'S', NULL, MENUNULL },
  137.         { /* "Save As..." (key-equivalent: 'A') */
  138.         &ProjItem[4],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  139.         (APTR)&ProjText[3], NULL, 'A', NULL, MENUNULL },
  140.         { /* "Print" (has sub-menu) */
  141.         &ProjItem[5],0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  142.         (APTR)&ProjText[4], NULL, NULL, &PrtItem[0], MENUNULL },
  143.         { /* "About..." */
  144.         &ProjItem[6],0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
  145.         (APTR)&ProjText[5], NULL, NULL, NULL, MENUNULL },
  146.         { /* "Quit" (key-equivalent: 'Q' */
  147.         NULL, 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
  148.         (APTR)&ProjText[6], NULL, 'Q', NULL, MENUNULL }
  149.     };
  150.  
  151. /* Menu Titles */
  152. struct Menu Menus[] = {
  153.         {&Menus[1],  0, 0, 63, 0, MENUENABLED, "Project",    &ProjItem[0]},
  154.         {&Menus[2], 70, 0, 39, 0, MENUENABLED, "Edit",       &EditItem[0]},
  155.         {NULL,     120, 0, 88, 0, MENUENABLED, "Settings",   &SettItem[0]},
  156.     };
  157.  
  158. /* A pointer to the first menu for easy reference */
  159. struct Menu *FirstMenu = &Menus[0];
  160.  
  161. /* Window Text for Explanation of Program */
  162. struct IntuiText WinText[] = {
  163.         {0, 0, JAM2, 0, 0, NULL, "How to do a Menu", NULL},
  164.         {0, 0, JAM2, 0, 0, NULL, "(with Style)", &WinText[0]}
  165.     };
  166.  
  167. /* Globals */
  168. struct Library  *IntuitionBase = NULL;
  169. struct Library  *GfxBase = NULL;
  170.  
  171. /* open all of the required libraries.  Note that we require
  172. ** Intuition V37, as the routine uses OpenWindowTags().
  173. */
  174. VOID main(int argc, char **argv)
  175. {
  176. LONG returnValue;
  177.  
  178. /* This gets set to RETURN_OK if everything goes well. */
  179. returnValue = RETURN_FAIL;
  180.  
  181. /* Open the Intuition Library */
  182. IntuitionBase = OpenLibrary("intuition.library", 37);
  183. if (IntuitionBase)
  184.     {
  185.     /* Open the Graphics Library */
  186.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33);
  187.     if (GfxBase)
  188.         {
  189.         returnValue = doWindow();
  190.  
  191.         CloseLibrary(GfxBase);
  192.         }
  193.     CloseLibrary(IntuitionBase);
  194.     }
  195. exit(returnValue);
  196. }
  197.  
  198. /* Open a window with some properly positioned text.  Layout and set
  199. ** the menus, then process any events received.  Cleanup when done.
  200. */
  201.  
  202. LONG doWindow()
  203. {
  204. struct Window *window;
  205. struct Screen *screen;
  206. struct DrawInfo *drawinfo;
  207. ULONG  signalmask, signals;
  208. ULONG  win_width, alt_width, win_height;
  209. LONG   returnValue = RETURN_FAIL;
  210. BOOL   done = FALSE;
  211.  
  212. if (screen = LockPubScreen(NULL))
  213.     {
  214.     if (drawinfo = GetScreenDrawInfo(screen))
  215.         {
  216.         /* get the colors for the window text */
  217.         WinText[0].FrontPen = WinText[1].FrontPen = drawinfo->dri_Pens[TEXTPEN];
  218.         WinText[0].BackPen  = WinText[1].BackPen  = drawinfo->dri_Pens[BACKGROUNDPEN];
  219.  
  220.         /* use the screen's font for the text */
  221.         WinText[0].ITextFont = WinText[1].ITextFont = screen->Font;
  222.  
  223.         /* calculate window size */
  224.         win_width  = 100 + IntuiTextLength(&(WinText[0]));
  225.         alt_width  = 100 + IntuiTextLength(&(WinText[1]));
  226.         if (win_width < alt_width)
  227.             win_width  = alt_width;
  228.         win_height = 1 + screen->WBorTop + screen->WBorBottom +
  229.                      (screen->Font->ta_YSize * 5);
  230.  
  231.         /* calculate the correct positions for the text in the window */
  232.         WinText[0].LeftEdge = (win_width - IntuiTextLength(&(WinText[0]))) >> 1;
  233.         WinText[0].TopEdge  = 1 + screen->WBorTop + (2 * screen->Font->ta_YSize);
  234.         WinText[1].LeftEdge = (win_width - IntuiTextLength(&(WinText[1]))) >> 1;
  235.         WinText[1].TopEdge  = WinText[0].TopEdge + screen->Font->ta_YSize;
  236.  
  237.         /* Open the window */
  238.         window = OpenWindowTags(NULL,
  239.             WA_PubScreen, screen,
  240.             WA_IDCMP,     IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUHELP,
  241.             WA_Flags,     WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
  242.                               WFLG_ACTIVATE | WFLG_NOCAREREFRESH,
  243.             WA_Left,      10,             WA_Top,       screen->BarHeight + 1,
  244.             WA_Width,     win_width,      WA_Height,    win_height,
  245.             WA_Title,     "Menu Example", WA_MenuHelp,  TRUE,
  246.             TAG_END);
  247.  
  248.  
  249.  
  250.         if (window)
  251.             {
  252.             returnValue = RETURN_OK;  /* program initialized ok */
  253.  
  254.             /* Give a brief explanation of the program */
  255.             PrintIText(window->RPort,&WinText[1],0,0);
  256.  
  257.             /* Adjust the menu to conform to the font (TextAttr) */
  258.             adjustMenus(FirstMenu, window->WScreen->Font);
  259.  
  260.             /* attach the menu to the window */
  261.             SetMenuStrip(window, FirstMenu);
  262.  
  263.             /* Set up the signals that you want to hear about ... */
  264.             signalmask = 1L << window->UserPort->mp_SigBit;
  265.  
  266.             /* And wait to hear from your signals */
  267.             while (!done)
  268.                 {
  269.                 signals = Wait(signalmask);
  270.                 if (signals & signalmask) done = handleIDCMP(window);
  271.                 };
  272.  
  273.             /* clean up everything used here */
  274.             ClearMenuStrip(window);
  275.             CloseWindow(window);
  276.             }
  277.         FreeScreenDrawInfo(screen,drawinfo);
  278.         }
  279.     UnlockPubScreen(NULL,screen);
  280.     }
  281. return(returnValue);
  282. }
  283.  
  284. /* print out what menu was selected.  Properly handle the IDCMP_MENUHELP
  285. ** events.  Set done to TRUE if quit is selected.
  286. */
  287. BOOL processMenus(USHORT selection, BOOL done)
  288. {
  289. USHORT flags;
  290. USHORT menuNum, itemNum, subNum;
  291.  
  292. menuNum = MENUNUM(selection);
  293. itemNum = ITEMNUM(selection);
  294. subNum  = SUBNUM(selection);
  295.  
  296. /* when processing IDCMP_MENUHELP, you are not guaranteed
  297. ** to get a menu item.
  298. */
  299. if (itemNum != NOITEM)
  300.     {
  301.     flags = ((struct MenuItem *)ItemAddress(FirstMenu,(LONG)selection))->Flags;
  302.     if (flags & CHECKED)
  303.         printf("(Checked) ");
  304.     }
  305.  
  306. switch (menuNum)
  307.     {
  308.     case 0:      /* Project Menu */
  309.         switch (itemNum)
  310.             {
  311.             case NOITEM: printf("Project Menu\n");        break;
  312.             case 0:      printf("New\n");                 break;
  313.             case 1:      printf("Open\n");                break;
  314.             case 2:      printf("Save\n");                break;
  315.             case 3:      printf("Save As\n");             break;
  316.             case 4:      printf("Print ");
  317.                 switch (subNum)
  318.                     {
  319.                     case NOSUB: printf("Item\n");  break;
  320.                     case 0:     printf("NLQ\n");   break;
  321.                     case 1:     printf("Draft\n"); break;
  322.                     }
  323.                 break;
  324.             case 5:      printf("About\n");               break;
  325.             case 6:      printf("Quit\n");   done = TRUE; break;
  326.             }
  327.         break;
  328.  
  329.  
  330.  
  331.  
  332.  
  333.     case 1:      /* Edit Menu */
  334.         switch (itemNum) {
  335.             case NOITEM: printf("Edit Menu\n"); break;
  336.             case 0:      printf("Cut\n");       break;
  337.             case 1:      printf("Copy\n");      break;
  338.             case 2:      printf("Paste\n");     break;
  339.             case 3:      printf("Erase\n");     break;
  340.             case 4:      printf("Undo\n");      break;
  341.             }
  342.         break;
  343.     case 2:      /* Settings Menu */
  344.         switch (itemNum) {
  345.             case NOITEM: printf("Settings Menu\n"); break;
  346.             case 0:      printf("Sound\n");            break;
  347.             case 1:      printf("Auto Save\n");        break;
  348.             case 2:      printf("Have Your Cake\n");   break;
  349.             case 3:      printf("Eat It Too\n");       break;
  350.             }
  351.         break;
  352.     case NOMENU: /* No menu selected, can happen with IDCMP_MENUHELP */
  353.         printf("no menu\n");
  354.         break;
  355.     }
  356. return(done);
  357. }
  358.  
  359. /* Handle the IDCMP messages.  Set done to TRUE if quit or closewindow is selected. */
  360. BOOL handleIDCMP(struct Window *win)
  361. {
  362. BOOL done;
  363. USHORT code, selection;
  364. struct IntuiMessage *message = NULL;
  365. ULONG  class;
  366.  
  367. done = FALSE;
  368.  
  369. /* Examine pending messages */
  370. while (message = (struct IntuiMessage *)GetMsg(win->UserPort)) {
  371.     class = message->Class;
  372.     code = message->Code;
  373.  
  374.     /* When we're through with a message, reply */
  375.     ReplyMsg((struct Message *)message);
  376.  
  377.     /* See what events occurred */
  378.     switch (class) {
  379.         case IDCMP_CLOSEWINDOW:
  380.             done = TRUE;
  381.             break;
  382.         case IDCMP_MENUHELP:
  383.             /*
  384.         ** The routine that handles the menus for IDCMP_MENUHELP must be very careful
  385.         ** it can receive menu information that is impossible under IDCMP_MENUPICK.
  386.         ** For instance, the code value on a IDCMP_MENUHELP may have a valid number
  387.         ** for the menu, then NOITEM and NOSUB. IDCMP_MENUPICK would get MENUNULL
  388.         ** in this case.  IDCMP_MENUHELP never come as multi-select items, and the
  389.         ** event terminates the menu processing session.
  390.             **
  391.             ** Note that I do not keep the return value from the processMenus() routine here--the
  392.         ** application should not quit if the user selects "help" over the quit menu item.
  393.             */
  394.             printf("IDCMP_MENUHELP: Help on ");
  395.             processMenus(code,done);
  396.             break;
  397.         case IDCMP_MENUPICK:
  398.             for ( selection = code; selection != MENUNULL;
  399.                   selection = (ItemAddress(FirstMenu,(LONG)selection))->NextSelect)
  400.                 {
  401.                 printf("IDCMP_MENUPICK: Selected ");
  402.                 done = processMenus(selection,done);
  403.                 }
  404.             break;
  405.         }
  406.     }
  407. return(done);
  408. }
  409. /* Steps thru each item to determine the maximum width of the strip */
  410. USHORT MaxLength(struct RastPort *textRPort, struct MenuItem *first_item, USHORT char_size)
  411. {
  412. USHORT maxLength;
  413. USHORT total_textlen;
  414. struct MenuItem  *cur_item;
  415. struct IntuiText *itext;
  416. USHORT extra_width;
  417. USHORT maxCommCharWidth;
  418. USHORT commCharWidth;
  419.  
  420. extra_width = char_size;  /* used as padding for each item. */
  421.  
  422. /* Find the maximum length of a command character, if any.
  423. ** If found, it will be added to the extra_width field.
  424. */
  425. maxCommCharWidth = 0;
  426. for (cur_item = first_item; cur_item != NULL; cur_item = cur_item->NextItem)
  427.     {
  428.     if (cur_item->Flags & COMMSEQ)
  429.         {
  430.         commCharWidth = TextLength(textRPort,&(cur_item->Command),1);
  431.         if (commCharWidth > maxCommCharWidth)
  432.             maxCommCharWidth = commCharWidth;
  433.         }
  434.     }
  435.  
  436. /* if we found a command sequence, add it to the extra required space.  Add
  437. ** space for the Amiga key glyph plus space for the command character.  Note
  438. ** this only works for HIRES screens, for LORES, use LOWCOMMWIDTH.
  439. */
  440. if (maxCommCharWidth > 0)
  441.     extra_width += maxCommCharWidth + COMMWIDTH;
  442.  
  443. /* Find the maximum length of the menu items, given the extra width calculated above. */
  444. maxLength = 0;
  445. for (cur_item = first_item; cur_item != NULL; cur_item = cur_item->NextItem)
  446.     {
  447.     itext = (struct IntuiText *)cur_item->ItemFill;
  448.     total_textlen = extra_width + itext->LeftEdge +
  449.           TextLength(textRPort, itext->IText, strlen(itext->IText));
  450.  
  451.     /* returns the greater of the two */
  452.     if (total_textlen > maxLength)
  453.         maxLength = total_textlen;
  454.     }
  455. return(maxLength);
  456. }
  457.  
  458. /* Set all IntuiText in a chain (they are linked through the NextText ** field) to the same font. */
  459. VOID setITextAttr(struct IntuiText *first_IText, struct TextAttr *textAttr)
  460. {
  461. struct IntuiText *cur_IText;
  462.  
  463. for (cur_IText = first_IText; cur_IText != NULL; cur_IText = cur_IText->NextText)
  464.     cur_IText->ITextFont = textAttr;
  465. }
  466.  
  467.  
  468. /* Adjust the MenuItems and SubItems */
  469. VOID adjustItems(struct RastPort *textRPort, struct MenuItem *first_item,
  470.                  struct TextAttr *textAttr, USHORT char_size, USHORT height,
  471.                  USHORT level, USHORT left_edge)
  472. {
  473. register USHORT item_num;
  474. struct   MenuItem *cur_item;
  475. USHORT   strip_width, subitem_edge;
  476.  
  477. if (first_item == NULL)
  478.     return;
  479.  
  480. /* The width of this strip is the maximum length of its members. */
  481. strip_width = MaxLength(textRPort, first_item, char_size);
  482.  
  483.  
  484.  
  485. /* Position the items. */
  486. for (cur_item = first_item, item_num = 0; cur_item != NULL; cur_item = cur_item->NextItem, item_num++)
  487.     {
  488.     cur_item->TopEdge  = (item_num * height) - level;
  489.     cur_item->LeftEdge = left_edge;
  490.     cur_item->Width    = strip_width;
  491.     cur_item->Height   = height;
  492.  
  493.     /* place the sub_item 3/4 of the way over on the item. */
  494.     subitem_edge = strip_width - (strip_width >> 2);
  495.  
  496.     setITextAttr((struct IntuiText *)cur_item->ItemFill, textAttr);
  497.     adjustItems(textRPort,cur_item->SubItem,textAttr,char_size,height,1,subitem_edge);
  498.     }
  499. }
  500.  
  501.  
  502. /* The following routines adjust an entire menu system to conform to the specified fonts' width and
  503. ** height.  Allows for Proportional Fonts. This is necessary for a clean look regardless of what the
  504. ** users preference in Fonts may be.  Using these routines, you don't need to specify TopEdge,
  505. ** LeftEdge, Width or Height in the MenuItem structures.
  506. **
  507. ** NOTE that this routine does not work for menus with images, but assumes that all menu items are
  508. ** rendered with IntuiText.
  509. **
  510. ** This set of routines does NOT check/correct if the menu runs off
  511. ** the screen due to large fonts, too many items, lo-res screen.
  512. */
  513. BOOL adjustMenus(struct Menu *first_menu, struct TextAttr *textAttr)
  514. {
  515. struct RastPort   textrp = {0};             /* Temporary RastPort */
  516. struct Menu      *cur_menu;
  517. struct TextFont  *font;                     /* Font to use */
  518. USHORT            start, char_size, height;
  519. BOOL              returnValue = FALSE;
  520.  
  521. /* open the font */
  522. if (font = OpenFont(textAttr))
  523.     {
  524.     SetFont(&textrp, font);       /* Put font into temporary RastPort */
  525.  
  526.     char_size = TextLength(&textrp, "n", 1);    /* Get the Width of the Font */
  527.  
  528.     /* To prevent crowding of the Amiga key when using COMMSEQ, don't allow the items to be less
  529.     ** than 8 pixels high.  Also, add an extra pixel for inter-line spacing.
  530.     */
  531.     if (font->tf_YSize > 8)
  532.         height = 1 + font->tf_YSize;
  533.     else
  534.         height = 1 + 8;
  535.  
  536.     start = 2;      /* Set Starting Pixel */
  537.  
  538.     /* Step thru the menu structure and adjust it */
  539.     for (cur_menu = first_menu; cur_menu != NULL; cur_menu = cur_menu->NextMenu)
  540.         {
  541.         cur_menu->LeftEdge = start;
  542.         cur_menu->Width = char_size +
  543.             TextLength(&textrp, cur_menu->MenuName, strlen(cur_menu->MenuName));
  544.         adjustItems(&textrp, cur_menu->FirstItem, textAttr, char_size, height, 0, 0);
  545.         start += cur_menu->Width + char_size + char_size;
  546.         }
  547.     CloseFont(font);              /* Close the Font */
  548.     returnValue = TRUE;
  549.     }
  550. return(returnValue);
  551. }
  552.